#include "./log_uart_recv_task.h"
#include "../driver/log_uart.h"
#include "../utils/message.h"
#include "./handler_task.h"
#include "../driver/ctrl.h"

namespace task {

using namespace driver;


static constexpr uint32_t PkgFail = static_cast<uint32_t>(-1);


void LogUartRecvTask::run() {
    utils::byte_view_t bw;
    while (true) {
        osStatus_t ret = logUart->poll(bw, 500);
        if (ret != osOK) {
            ctrl::led_toggle();
            continue;
        }
        uint32_t index = 0;
        while (index < bw.len) {
            uint32_t ret = pkg_exec(bw.buf + index, bw.len - index);
            if (ret == PkgFail) {
                break;
            }
            index += ret;
        }
    }
}

uint32_t LogUartRecvTask::pkg_exec(const uint8_t *buf, uint32_t len) {
    using message_t = utils::message_t;
    using namespace utils;

    uint16_t head = decode_uint16(buf);
    if (head != proto::Head) {
        return PkgFail;
    }
    uint16_t size = decode_uint16(buf + 2);
    if ((size < 8) || (size > len)) {
        return PkgFail;
    }

    uint8_t s = alg::sun_xor(buf + 6, size - 8);
    if (s != buf[size - 2]) {
        return PkgFail;
    }
    if (buf[size - 1] != proto::End) {
        return PkgFail;
    }

    logUart->write(proto::Ack);
    message_t msg(buf, len, message_t::Uart::Log);
    handlerTask->post(msg);

    return size;
}

}
